package WGH;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

public class Evaluator {
	private AssignmentTable at;
	private GroupTable gt;
	private ProjectTable projt;
	private PersonTable pt;
	private RoomTable rt;
	private int sc1;
	private ArrayList<Person> sc1_p;
	private int sc2;
	private ArrayList<Person> sc2_p;
	private int sc3;
	private ArrayList<Group> sc3_g;
	private int sc4;
	private ArrayList<Room> sc4_r;
	private int sc5;
	private int sc6;
	private int sc7;
	private int sc8;
	private int sc9;
	private int sc10;
	private int sc11;
	private int sc12;
	private int sc13;
	private int sc14;
	private int sc15;
	private int sc16;

	
	public Evaluator(AssignmentTable at, GroupTable gt, ProjectTable projt, PersonTable pt, RoomTable rt){
		this.at = at;
		this.gt = gt;
		this.projt = projt;
		this.pt = pt;
		this.rt = rt;
	}
	
	public int eval_sc1(){
		this.sc1 = 0;
		this.sc1_p = new ArrayList<Person>();
		for(Map.Entry<String, Group> entry:gt.getGT().entrySet()){
			if(entry.getValue().getGroupHead()!=null&&at.getAT().get(entry.getValue().getGroupHead())!=null){
				Person p = entry.getValue().getGroupHead();
				Room r = at.getAT().get(p);
				if(r.getRoomSize()!=RoomSize.LARGEROOM){
					sc1_p.add(p);
					sc1 -= 40;
				}
			}
		}
		return sc1;
	}
	public int eval_sc2(){
		this.sc2 = 0;
		this.sc2_p = new ArrayList<Person>();
		for(Map.Entry<String, Group> entry : gt.getGT().entrySet()){
			Group g = entry.getValue();
			if(g.getGroupHead()!=null&&at.getAT().get(g.getGroupHead())!=null){
				Person gh = g.getGroupHead();
				Room r_gh = at.getAT().get(gh);
				for(Person p : g.groupMember){
					if(p!=gh){
						Room r_gmem = at.getAT().get(p);
						if(!r_gh.CloseTo.contains(r_gmem)){
							sc2 -= 2;
							sc2_p.add(p);
						}
					}
				}
			}
		}
		return sc2;
	}
	public int eval_sc3(){
		this.sc3 = 0;
		this.sc3_g = new ArrayList<Group>();
		for(Map.Entry<String, Group> entry : gt.getGT().entrySet()){
			Group g = entry.getValue();
			int ghCloseS = 0;
			if(g.getGroupHead()!=null){
				Person gh = g.getGroupHead();
				Room r_gh = at.getAT().get(gh);
				for(Person p : g.groupMember){
					if(p.getRole() == ROLE.SECRETARY){
						Room r_s = at.getAT().get(p);
						if(!r_gh.CloseTo.contains(r_s)){
							ghCloseS = -30;
						}else{
							ghCloseS = 0;
						}
					}			
				}
			}
			if(ghCloseS == -30)	sc3_g.add(g);
			this.sc3 += ghCloseS;
		}
		return sc3;
	}
	public int eval_sc4(){
		this.sc4 = 0;
		ArrayList<Room> tmp = new ArrayList<Room>();
		for(Map.Entry<Person, Room> entry : at.getAT().entrySet()){
			Person p = entry.getKey();
			if(p.getRole() == ROLE.SECRETARY){
				Room r = entry.getValue();
				if(!tmp.contains(r)){
					tmp.add(r);
				}else{
					tmp.remove(r);
				}
			}
		}
		this.sc4_r = tmp;
		this.sc4 = tmp.size() * (-5);
		return sc4;
	}
	public int eval_sc5(){
		this.sc5 = 0;
		for(Map.Entry<String, Group> entry : gt.getGT().entrySet()){
			Group g = entry.getValue();
			if(g.getGroupManager()!=null){
				Person gm = g.getGroupManager();
				Room r_gm = at.getAT().get(gm);
				int g_mark = -20;
				for(Person p:g.groupMember){
					if(p.getRole()==ROLE.SECRETARY){
						if(r_gm.CloseTo.contains(at.getAT().get(p))){
							g_mark = 0;
							break;
						}
					}
				}
				this.sc5 += g_mark;
			}
		}
		return this.sc5;
	}
	public int eval_sc6(){
		this.sc6 = 0;
		for(Map.Entry<String, Group> entry : gt.getGT().entrySet()){
			int ghCgm = -20;
			Group g = entry.getValue();
			if(g.getGroupHead() != null && g.getGroupManager() != null){
				Person gh = g.getGroupHead();
				Room r_gh = at.getAT().get(gh);
				Person gm = g.getGroupManager();
				Room r_gm = at.getAT().get(gm);
				if(r_gm.CloseTo.contains(r_gh))	ghCgm = 0;
				else this.sc6 += ghCgm;
			}
		}
		return this.sc6;
	}
	public int eval_sc7(){
		this.sc7 = 0;
		for(Map.Entry<String, Group> entry : gt.getGT().entrySet()){
			Group g = entry.getValue();
			if(g.getGroupManager()!=null&&at.getAT().get(g.getGroupManager())!=null){
				Person gm = g.getGroupManager();
				Room r_gm = at.getAT().get(gm);
				for(Person p : g.groupMember){
					Room r_gmem = at.getAT().get(p);
					if(gm!=p&&!r_gm.CloseTo.contains(r_gmem))	this.sc7 -= 2;
				}
			}
		}
		return sc7;
	}
	public int eval_sc8(){
		this.sc8 = 0;
		for(Map.Entry<String, Project> entry : projt.getPrjTable().entrySet()){
			Project prj = entry.getValue();
			if(prj.getProjectHead()!=null){
				Person ph = prj.getProjectHead();
				Room r_ph = at.getAT().get(ph);
				for(Person p : prj.getProjectMembers()){
					if(p!=ph){
						Room r_pmem = at.getAT().get(p);
						if(!r_ph.CloseTo.contains(r_pmem)){
							sc8 -= 5;
						}
					}
				}
			}
		}
		return sc8;
	}
	public int eval_sc9(){
		this.sc9 = 0;
		for(Map.Entry<String, Project> entry : projt.getPrjTable().entrySet()){
			if(entry.getValue().isLargeProject()){
				int mark = -10;
				Project prj = entry.getValue();
				if(prj.getProjectHead()!=null){
					Person prjh = prj.getProjectHead();
					Room r_prjh = at.getAT().get(prjh);
					if(prjh.getGroup()!=null){
						Group g = prjh.getGroup();
						for(Person p:g.groupMember){
							if(p.getRole()==ROLE.SECRETARY&&at.getAT().get(p)!=null){
								Room r_s = at.getAT().get(p);
								if(r_prjh.CloseTo.contains(r_s)){
									mark = 0;
									break;
								}
							}
						}
						this.sc9 += mark;
					}
				}
			}
		}
		return this.sc9;
	}
	public int eval_sc10(){
		this.sc10 = 0;
		for(Map.Entry<String, Project> entry : projt.getPrjTable().entrySet()){
			int mark = -10;
			if(entry.getValue().isLargeProject()){
				Project prj = entry.getValue();
				if(prj.getProjectHead()!=null){
					Person prjh = prj.getProjectHead();
					if(prjh.getGroup().getGroupHead()!=null){
						Person gh = prjh.getGroup().getGroupHead();
						Room r_gh = at.getAT().get(gh);
						Room r_prjh = at.getAT().get(prjh);
						System.out.println(r_gh);
						System.out.println(r_prjh);
						if(r_gh.CloseTo.contains(r_prjh))	mark = 0;
					}
					this.sc10 += mark;
				}
			}
		}
		return this.sc10;
	}
	public int eval_sc11(){
		this.sc11 = 0;
		ArrayList<Room> rl = new ArrayList<Room>();
		for(Map.Entry<String, Person> entry : pt.getPT().entrySet()){
			Person p = entry.getValue();
			if(p.isSmoker()){
				Room r = at.getAT().get(p);
				if(rl.contains(r)){
					rl.remove(r);
				}else{
					rl.add(r);
				}
			}
		}
		for(Map.Entry<String, Person> entry : pt.getPT().entrySet()){
			Person p = entry.getValue();
			if(!p.isSmoker()){
				Room r = at.getAT().get(p);
				if(rl.contains(r))	this.sc11 -= 50;
			}
		}
		return this.sc11;
	}
	public int eval_sc12(){
		this.sc12 = 0;
		for(Map.Entry<String, Project> entry:projt.getPrjTable().entrySet()){
			Project prj = entry.getValue();
			int mark = 0;
			if(prj.getProjectMembers().size() >= 2){
				ArrayList<Room> rl = new ArrayList<Room>();
				for(Person p :prj.getProjectMembers()){
					Room r = at.getAT().get(p);
					if(!rl.contains(r)){
						rl.add(r);
					}else{
						mark -= 14;
					}
				}
			}
			this.sc12 += mark;
		}
		return this.sc12;
	}
	public int eval_sc13(){
		this.sc13 = 0;
		ArrayList<Room> rl = new ArrayList<Room>();
		for(Map.Entry<String, Person> entry:pt.getPT().entrySet()){
			Person p = entry.getValue();
			if(p.getRole()!=ROLE.SECRETARY&&p.isHacker()){
				Room r = at.getAT().get(p);
				if(rl.contains(r))	rl.remove(r);
				else	rl.add(r);
			}
		}
		for(Map.Entry<Person, Room> entry:at.getAT().entrySet()){
			Person p = entry.getKey();
			if(p.getRole()!=ROLE.SECRETARY&&!p.isHacker()){
				Room r = at.getAT().get(p);
				if(rl.contains(r)){
					this.sc13 -= 2;
				}
			}
		}
		return this.sc13;
	}
	public int eval_sc15(){
		this.sc15 = 0;
		for(Map.Entry<Person, Room> entry:at.getAT().entrySet()){
			Person p1 = entry.getKey();
			Room r1 = entry.getValue();
			for(Map.Entry<Person, Room> entry1:at.getAT().entrySet()){
				Person p2 = entry1.getKey();
				Room r2 = entry1.getValue();
				if(p2!=p1&&r1==r2&&!p1.WorkWith.contains(p2)){
					this.sc15 -= 3;
					break;
				}
			}
		}
		return this.sc15;
	}
	public int eval_sc16(){
		this.sc16 = 0;
		for(Map.Entry<Person, Room> entry:at.getAT().entrySet()){
			Person p1 = entry.getKey();
			Room r1 = entry.getValue();
			for(Map.Entry<Person, Room> entry1:at.getAT().entrySet()){
				Person p2 = entry1.getKey();
				Room r2 = entry1.getValue();
				if(p2!=p1&&r1==r2&&r1.getRoomSize()==RoomSize.SMALLROOM){
					this.sc16 -= 25;
					break;
				}
			}
		}
		return this.sc16;
	}
	public int eval_total(){
		int total = 0;
		total = eval_sc1() + eval_sc2() + eval_sc3() + eval_sc4() + eval_sc5() + eval_sc6() + eval_sc7() + eval_sc8() + eval_sc9() + eval_sc10() + eval_sc11() + eval_sc12() + eval_sc13() + eval_sc15() + eval_sc16();
		return total;
	}
	public int eval_total_opt(){
		int mark = 0;
		int temp = 0;
		for(Map.Entry<String, Group> entry: this.gt.getGT().entrySet()){
			Group g = entry.getValue();
			if(g.getGroupHead()!=null&&g.getGroupHead().getRoom()!=null){
				Person groupHead =g.getGroupHead();
				Person groupManager = g.getGroupManager();
				Room room_groupHead = groupHead.getRoom();
				//sc1
				if(room_groupHead.getRoomSize()!=RoomSize.LARGEROOM){
					mark -= 40;
				}
				//sc2 && sc7
				for(Person p : g.groupMember){
					if(!Person.close(groupHead, p))	mark -= 2;
					if(!Person.close(groupManager, p))	mark -= 2;
				}
				//sc3
				for(Person p : g.groupSecretary){
					if(groupHead.close(p)){
						temp = 0;
						break;
					}else{
						temp = -30;
					}
				}
				mark += temp;
				//sc5
				for(Person p : g.groupSecretary){
					if(groupManager.close(p)){
						temp = 0;
						break;
					}else{
						temp = -20;
					}
				}
				//sc6
				if(!groupManager.close(groupHead)){
					mark -= 20;
				}
				mark += temp;
			}
		}
		for(Map.Entry<String, Project> entry : this.projt.getPrjTable().entrySet()){
			Project j = entry.getValue();
			if(j.getProjectHead()!=null){
				Person projectHead = j.getProjectHead();
				for(Person p : j.getProjectMembers()){
					//sc8
					if(!projectHead.close(p))	mark -= 5;
				}
			}
			if(j.isLargeProject()&&j.getProjectHead()!=null){
				Group g = j.getProjectHead().getGroup();
				Person lph = j.getProjectHead();
				for(Person p : g.groupSecretary){
					//sc9
					if(lph.close(p)){
						temp = 0;
						break;
					}else{
						temp = -10;
					}
						
				}
				mark += temp;
				//sc10
				if(!lph.close(g.getGroupHead()))	mark -= 10;
			}
		}
		
		for(Map.Entry<String, Room> entry : this.rt.getRT().entrySet()){
			Room r = entry.getValue();
			if(r.getP1()!=null&&r.getP2()!=null){
				Person p1 = r.getP1();
				Person p2 = r.getP2();
				if(p1!=p2){
					//sc4
					if((p1.getRole()==ROLE.SECRETARY && p2.getRole()!=ROLE.SECRETARY) || (p1.getRole()!=ROLE.SECRETARY && p2.getRole()==ROLE.SECRETARY)){
						mark -= 5;
					}
					//sc11
					if((p1.isSmoker()&&!p2.isSmoker()) || (!p1.isSmoker()&&p2.isSmoker())){
						mark -= 50;
					}
					//sc12
					if(p1.getProject() == p2.getProject()&&p1!=p2)	mark -= 7;
					//sc13
					if(p1.getRole()!=ROLE.SECRETARY || p2.getRole()!=ROLE.SECRETARY){
						if(p1.isHacker()!=p2.isHacker())	mark -= 2;
					}
					//sc15, can be changed to -6 if want to match with Professor Kremer's result
					if(!p1.WorkWith.contains(p2)){
						mark -= 3;

					}
					//sc16,can be changed to -50 if want to match with Professor Kremer's result
					if(r.getRoomSize()==RoomSize.SMALLROOM){
						mark -= 25;
					}
				}
			}
		}
		
		return mark;
	}
}
